package top.codef.crypt.rsa;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class RSAPrivateKeyPair {

	private RSAPrivateKey rsaPrivateKey;

	private String algorithm = "RSA";

	private String signAlgorithm = "MD5withRSA";

	public RSAPrivateKeyPair(RSAPrivateKey rsaPrivateKey) {
		this.rsaPrivateKey = rsaPrivateKey;
	}

	public RSAPrivateKeyPair(RSAPrivateKey rsaPrivateKey, SignAlgorithm signAlgorithm, RsaAlgorithm rsaAlgorithm) {
		this.rsaPrivateKey = rsaPrivateKey;
		this.signAlgorithm = signAlgorithm.getSignType();
		this.algorithm = rsaAlgorithm.getValue();
	}

	public RSAPrivateKeyPair(String privateKeyBase64) {
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
			this.rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			e.printStackTrace();
		}

	}

	public RSAPrivateKeyPair(String privateKeyBase64, String algorithm, String signAlgorithm) {
		this.algorithm = algorithm;
		this.signAlgorithm = signAlgorithm;
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
			this.rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @return the algorithm
	 */
	public String getAlgorithm() {
		return algorithm;
	}

	/**
	 * @param algorithm the algorithm to set
	 */
	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}

	/**
	 * @return the signAlgorithm
	 */
	public String getSignAlgorithm() {
		return signAlgorithm;
	}

	/**
	 * @param signAlgorithm the signAlgorithm to set
	 */
	public void setSignAlgorithm(String signAlgorithm) {
		this.signAlgorithm = signAlgorithm;
	}

	/**
	 * @param rsaPrivateKey the rsaPrivateKey to set
	 */
	public void setRsaPrivateKey(RSAPrivateKey rsaPrivateKey) {
		this.rsaPrivateKey = rsaPrivateKey;
	}

	public RSAPrivateKey getRsaPrivateKey() {
		return rsaPrivateKey;
	}

	public String getPrivatekeyBase64() {
		return Base64.encodeBase64String(rsaPrivateKey.getEncoded());
	}

	public byte[] sign(byte[] content) {
		try {
			Signature signature = Signature.getInstance(signAlgorithm);
			signature.initSign(rsaPrivateKey);
			signature.update(content);
			return signature.sign();
		} catch (Exception e) {
			System.err.println("签名错误");
			e.printStackTrace();
		}
		return null;
	}

	public byte[] encrypt(byte[] bs) {
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, rsaPrivateKey);
			return cipher.doFinal(bs);
		} catch (Exception e) {
			System.err.println("加密异常");
			e.printStackTrace();
		}
		return null;
	}

	public byte[] decypt(byte[] bs) {
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
			return cipher.doFinal(bs);
		} catch (Exception e) {
			System.err.println("解密异常");
			e.printStackTrace();
		}
		return null;
	}

}
